package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsBatch;
import com.zmj.sy.mom.srv.aps.bean.entity.order.Order;
import com.zmj.sy.mom.srv.aps.bean.vo.apsbatch.ApsBatchListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectItemResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseSelectResVo;
import com.zmj.sy.mom.srv.aps.mapper.ApsBatchMapper;
import com.zmj.sy.mom.srv.aps.mapper.OrderMapper;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class ApsBatchService {

    private final ApsBatchMapper apsBatchMapper;

    private final OrderMapper orderMapper;

    private final StringRedisTemplate stringRedisTemplate;

    private final ObjectMapper objectMapper;

    private final Environment environment;

    @Transactional
    public void add(ApsBatch first) {
        apsBatchMapper.insert(first);
    }

    public BaseSelectResVo select() {


        LambdaQueryWrapper<ApsBatch> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ApsBatch::getStatus, 2);
        List<ApsBatch> apsBatchList = apsBatchMapper.selectList(wrapper);

        List<Integer> batchIds = apsBatchList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());

        List<Order> orderList = new ArrayList<>();
        if (CollUtil.isNotEmpty(batchIds)) {
            orderList = orderMapper.selectList(Wrappers.<Order>lambdaQuery().in(Order::getBatchId, batchIds));
        }
//        Map<Integer, List<Order>> collect = orderList.stream().collect(Collectors.groupingBy(Order::getBatchId));

        List<BaseSelectItemResVo> collect1 = apsBatchList.stream()
                .map(e -> {
                    BaseSelectItemResVo r = new BaseSelectItemResVo();
                    r.setValue(e.getId());
//                    r.setText(collect.get(e.getId()).stream().map(e1 -> e1.getOrderCode() + e1.getMaterName()).collect(Collectors.joining("],[", "[", "]")));
                    return r;
                })
                .collect(Collectors.toList());

        return BaseSelectResVo.of(collect1);


    }

    public ApsBatch getNoPubLast() {
        LambdaQueryWrapper<ApsBatch> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ApsBatch::getStatus, 1);
        wrapper.orderByDesc(ApsBatch::getId);
        wrapper.last("limit 1");
        return apsBatchMapper.selectOne(wrapper);
    }

    public ApsBatch getById(Integer sourceBatchId) {
        return apsBatchMapper.selectById(sourceBatchId);
    }

    public BaseListResVo<ApsBatchListResVo> list() {

        LambdaQueryWrapper<ApsBatch> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ApsBatch::getStatus, 2);
        wrapper.orderByDesc(ApsBatch::getSchedulingDateTime);
        List<ApsBatch> apsBatchList = apsBatchMapper.selectList(wrapper);

        List<ApsBatchListResVo> collect = apsBatchList.stream()
                .map(e -> {
                    ApsBatchListResVo r = new ApsBatchListResVo();
                    BeanUtils.copyProperties(e, r);
                    r.setType(1);
                    r.setNewId(r.getType() + "-" + r.getId());
                    return r;
                })
                .collect(Collectors.toList());

        LambdaQueryWrapper<Order> wp1 = Wrappers.lambdaQuery();
        wp1.isNotNull(Order::getBatchId);
        wp1.ge(Order::getOrderStatus, 6);
        List<Order> orderList = orderMapper.selectList(wp1);
        Map<Integer, List<Order>> collect1 = orderList.stream().collect(Collectors.groupingBy(Order::getBatchId));

        for (ApsBatchListResVo batch : collect) {
            List<Order> orderList1 = collect1.get(batch.getId());
            if (CollUtil.isEmpty(orderList1)) {
                continue;
            }


            List<ApsBatchListResVo> collect2 = orderList1.stream().map(e -> {
                        ApsBatchListResVo resVo = new ApsBatchListResVo();
                        resVo.setId(e.getId());
                        resVo.setBatchNo(e.getOrderCode());
                        resVo.setMaterName(e.getMaterName());
                        resVo.setMaterCode(e.getMaterCode());
                        resVo.setOrderQty(e.getOrderQty());
                        resVo.setType(2);
                        resVo.setNewId(resVo.getType() + "-" + resVo.getId());
                        return resVo;
                    })
                    .collect(Collectors.toList());
            batch.getData().addAll(collect2);
        }

        return new BaseListResVo<>(collect);
    }

    @SneakyThrows
    public void cache(List<ApsBatchListResVo> reqVo) {
        ValueOperations<String, String> valueOp = stringRedisTemplate.opsForValue();
        valueOp.set(environment.getProperty("spring.application.name") + ":apsBatch:cache" , objectMapper.writeValueAsString(reqVo), 1, TimeUnit.DAYS);
    }

    public List<ApsBatchListResVo> move(List<ApsBatchListResVo> reqVo) {
        // 0.无ID的批次ID保存

        // 1.取出数据库的批次
        BaseListResVo<ApsBatchListResVo> list = list();
        int startIndex = -1;
        for (int i = 0; i < reqVo.size(); i++) {
            ApsBatchListResVo apsBatchCacheReqVo = reqVo.get(i);
            if(apsBatchCacheReqVo.getId() == null){
                startIndex = i;
                break;
            }

            if(list.getData().size() < i){
                startIndex = i;
                break;
            }


            if(!apsBatchCacheReqVo.getId().equals(list.getData().get(i).getId())){
                startIndex = i;
                break;
            }

            if(apsBatchCacheReqVo.getData().size() != list.getData().get(i).getData().size()){
                startIndex = i;
                break;
            }

            boolean b = false;
            for (int j = 0; j < apsBatchCacheReqVo.getData().size(); j++) {
                ApsBatchListResVo resVo = apsBatchCacheReqVo.getData().get(j);
                Integer orderId = resVo.getId();

                if (!list.getData().get(i).getData().get(j).getId().equals(orderId)) {
                    b = true;
                    break;
                }
            }
            if(b){
                startIndex = i;
                break;
            }

        }

        if(startIndex < 0){
            return new ArrayList<>();
        }

        // 2.判断每个位置的批次ID是否相同，如果相同判断子订单长度和内容是否相同，如果都相同跳过

        // 3.如果不同则从此开始 移单
        return reqVo.subList(0, reqVo.size());

    }

    public void clearCache() {
        stringRedisTemplate.delete(environment.getProperty("spring.application.name") + ":apsBatch:cache" );
    }

    @SneakyThrows
    public List<ApsBatchListResVo> cacheList() {
        ValueOperations<String, String> valueOp = stringRedisTemplate.opsForValue();
        String s = valueOp.get(environment.getProperty("spring.application.name") + ":apsBatch:cache");
        return objectMapper.readValue(s, new TypeReference<List<ApsBatchListResVo>>() {});
    }
}
